 package com.bill.gaty.audrey.expressionarithmethique.components;

import javax.swing.JOptionPane;

import com.bill.gaty.audrey.expressionarithmethique.components.util.SaisieUtil;
import com.bill.gaty.audrey.expressionarithmethique.domain.Noeud;
import com.bill.gaty.audrey.expressionarithmethique.exception.BadExpressionException;
import com.bill.gaty.audrey.expressionarithmethique.exception.FunctionNotSupportedException;
 public class Derivateur  {
	 Noeud expressionAderive=null   ;
	 private Character variable =null;
	 private Noeud expressionderive=null;
	 public Derivateur(Noeud expressionAderive,char variable){
	 	this.expressionAderive=expressionAderive;
	 	this.variable=variable;
	 	
	 }
	 public Derivateur(String expressionAderive,char variable) throws BadExpressionException{
	 	this.expressionAderive=new SaisieUtil(expressionAderive).getlisteDesNoeud();
	 	this.variable=variable;
	 	
	 }
	 public Derivateur(String expressionAderive) throws BadExpressionException{
	 	this.expressionAderive=new SaisieUtil(expressionAderive).getlisteDesNoeud();
	  
	 	
	 }
	 public Derivateur(){
	 	
	 }
	 public Noeud getexpressionAderive(){return this.expressionAderive;}

	 public Noeud deriverExpression() throws FunctionNotSupportedException{
	 	if(variable==null||this.variable==' ') {
	 		//System.out.println("donner la variable de derivation>>>");
	 		this.variable=(JOptionPane.showInputDialog(null,"donner la variable de derivation")).toLowerCase().charAt(0);
	 	}
	 	this.expressionderive=derivee(this.expressionAderive,this.variable);
	 	return this.expressionderive;
	 }


	 public   Noeud derivee(Noeud fon, Character var) throws FunctionNotSupportedException {
		 if(null==var||var==' ') {
		 		//System.out.println("donner la variable de derivation>>>");
			 var=(JOptionPane.showInputDialog(null,"donner la variable de derivation")).toLowerCase().trim().charAt(0);
		 	}
         if(null==fon)return null;
	 if (fon.isConstante())
	 	return new Noeud(0);
	 else if (fon.isVariable())
	 	if (fon.getLettreVariable()==var)
	 		return new Noeud(1 );
	      else
	     	 return new Noeud(0);
	 else if (fon.isPlus())//derive(u+V)=derivee(u)+derivee(V)
	 	return Noeud.plus(derivee(fon.getOperandeGauche(), var), derivee(fon.getOperandeDroite(), var));
	 else if (fon.isMoins())
	 	return  Noeud.moins(derivee(fon.getOperandeGauche(), var), derivee(fon.getOperandeDroite(), var)   );
	 else if (fon.isMul()){
	 	return  Noeud.plus(Noeud.fois(derivee(fon.getOperandeGauche(), var   ), fon.getOperandeDroite()   ),
	 Noeud.fois(fon.getOperandeGauche(), derivee(fon.getOperandeDroite(), var   )   )   );//(UV)'=U'*V+U*V'
	 } else if (fon.isPow()){
	 	
	 	return Noeud.fois( derivee(Noeud.fois(fon.getOperandeDroite(),new Noeud("log",fon.getOperandeGauche())),var),fon);
	 	
	 //(U^v)'=exp(V*log(U))'
	 }
	 else if (fon.isDiv()){
	 	
	 	return Noeud.div( Noeud.moins( Noeud.fois(derivee(fon.getOperandeGauche(), var   ), fon.getOperandeDroite()   ),
	 		Noeud.fois(fon.getOperandeGauche(), derivee(fon.getOperandeDroite(), var   )   )   ),
	 		Noeud.pow(fon.getOperandeDroite(), new Noeud(2))  )   ;//(u/v)'=(u'*v-u*v')/(v^2);
	  //cas des fonction 
	 }
	 else if (SaisieUtil.getfonctions().get("-")==fon.getadresseFonction() )//-
	 	return new Noeud(fon.getadresseFonction(), derivee(fon.getOperandeGauche(), var   )   );
	 else if (SaisieUtil.getfonctions().get("acos")==fon.getadresseFonction() )//-
		 	return  Noeud.fois(derivee(fon.getOperandeGauche(), var),new Noeud("-",Noeud.div(new Noeud(1), new Noeud("sqrt",Noeud.moins(new Noeud(1), Noeud.pow(fon.getOperandeGauche(), new Noeud(2)))))));
	
	 else if (SaisieUtil.getfonctions().get("asin")==fon.getadresseFonction() )//-
		 return  Noeud.fois(derivee(fon.getOperandeGauche(), var), Noeud.div(new Noeud(1), new Noeud("sqrt",Noeud.moins(new Noeud(1), Noeud.pow(fon.getOperandeGauche(), new Noeud(2))))));
	 else if (SaisieUtil.getfonctions().get("atan")==fon.getadresseFonction() )//-
		 return  Noeud.fois(derivee(fon.getOperandeGauche(), var), Noeud.div(new Noeud(1),  Noeud.plus(new Noeud(1), Noeud.pow(fon.getOperandeGauche(), new Noeud(2)))));
		
	 else if (SaisieUtil.getfonctions().get("cosh")==fon.getadresseFonction() )//-
		 return  Noeud.fois(derivee(fon.getOperandeGauche(), var),new Noeud("sinh",fon.getOperandeGauche()));
	 else if (SaisieUtil.getfonctions().get("sinh")==fon.getadresseFonction() )//-
		 return  Noeud.fois(derivee(fon.getOperandeGauche(), var),new Noeud("cosh",fon.getOperandeGauche()));
	 else if (SaisieUtil.getfonctions().get("tanh")==fon.getadresseFonction() )//-
		 return  Noeud.fois(derivee(fon.getOperandeGauche(), var),  Noeud.moins( new Noeud(1),Noeud.pow(new Noeud("tanh",fon.getOperandeGauche()), new Noeud(2)) ));
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("sin"))
	 	return Noeud.fois( derivee(fon.getOperandeGauche(), var   )  ,new Noeud(SaisieUtil.getfonctions().get("cos"), fon.getOperandeGauche()   ) );
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("cos"))
	 	return new Noeud(SaisieUtil.getfonctions().get("-"), Noeud.fois(derivee(fon.getOperandeGauche(), var   ) ,new Noeud(SaisieUtil.getfonctions().get("sin"), fon.getOperandeGauche()   )
	   )   );
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("exp")||fon.getadresseFonction() == SaisieUtil.getfonctions().get("e"))
	 	return  Noeud.fois( derivee(fon.getOperandeGauche(), var   )  ,fon );
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("cotan"))
		 return derivee(Noeud.div(new Noeud(1), new Noeud("tan",fon.getOperandeGauche())), var);
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("tan"))
	 	
	 	return Noeud.div( derivee(fon.getOperandeGauche(),var)  , 
	 			Noeud.fois(new Noeud(SaisieUtil.getfonctions().get("cos"),fon.getOperandeGauche()),new Noeud(SaisieUtil.getfonctions().get("cos"),fon.getOperandeGauche())));
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("sinh"))
	 	return Noeud.fois(derivee(fon.getOperandeGauche(),var), new Noeud(SaisieUtil.getfonctions().get("cosh"),fon.getOperandeGauche()));
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("cosh"))
	 	return Noeud.fois(derivee(fon.getOperandeGauche(),var), new Noeud(SaisieUtil.getfonctions().get("sinh"),fon.getOperandeGauche()));
	 else if (fon.getadresseFonction() == SaisieUtil.getfonctions().get("tanh"))

	 	return Noeud.div( derivee(fon.getOperandeGauche(),var)  , 
	 			Noeud.pow(new Noeud(SaisieUtil.getfonctions().get("cosh"),
	 					fon.getOperandeGauche()),new Noeud(SaisieUtil.getfonctions().get("cosh"),fon.getOperandeGauche())));

	 else if(fon.getadresseFonction() == SaisieUtil.getfonctions().get("log")||fon.getadresseFonction() == SaisieUtil.getfonctions().get("ln")) /* fon->fonction == log */
	 	return Noeud.div(derivee(fon.getOperandeGauche(), var   ), fon.getOperandeGauche()   );//(log(u)'=u'/u;
	 //(log(u)'=u'/u;
	 else if (fon.isFonctionRacineCarree()){
		 //u'/2*sqrt(u)
		 return Noeud.div(derivee(fon.getOperandeGauche(), var),Noeud.fois(new Noeud(2), fon)      );
	   
	 } 
	 else  
  throw new FunctionNotSupportedException(SaisieUtil.get(fon.getadresseFonction()));
	 
	   
	 }
	 public Noeud getexpressionderive(){
	 	return expressionderive;
	 	
	 }
	 public void setVariable(char a){
	 	 this.variable=a;
	 }
	 public char getVariable(){
	 	 return variable;
	 }
	 public void setexpressionAderive(Noeud a){
	 	this.expressionAderive=a;
	 }

	 }

 
 
 
 
 
 
 
 
 
 